
// 工具1：Partial
// 需求：定义一个相对完整的表达客户信息的数据接口

interface IPseron {
	id:string
	phone:number
	carId:string
}
// 完整客户信息
let pp:IPseron = {
	id:'xxxxx',
	phone:13677778888,
	carId:'川A66666'
}

//领奖数据包，使用Partial将IPerson接口内部字段变为可选
let info:Partial<IPseron> = {
	phone:13677778888
}

// 工具2：Required
// 将原本接口中的可选字段，变为必选
interface IPerson1{
	id?:string
	phone?:number
	carId?:string
}
//登记完整用户信息
let p1:Required<IPerson1> = {
	id:'xxxx',
	phone:13677778888,
	carId:'川A66666'
}
//领奖信息
let info1:IPerson1 = {
	carId:'川A66666'
}

//工具3：Readonly
// 将某个接口中的字段，设为只读
let p3:Readonly<IPerson1> = {
	id:'11333444',
	phone:14566666444
}
// p3.id = 'xxxxxx'  //此处会告警，尝试修改只读属性


// 工具4：Pick<被处理的接口,字段名称>
// 从某个字段比较多的接口中，挑选部分字段作为新的接口约束
interface IPerson2 {
	id:string
	phone:number
	carId:string
}
//完整信息
let p2:IPerson2 = {
	id:'xxxx',
	phone:13677778888,
	carId:'川A66666'
}
// 通过识别车牌号，自动登记免费洗车
let info2:Pick<IPerson2,'carId'|'phone'> = {
	carId:'川A66666',
	phone:13677778888
}

//工具5：Record<key的类型,值的类型>
//方法1：不使用Record
// interface DetailType {
// 	title:string
// 	desc:string
// }
// interface PageType {
// 	about:DetailType,
// 	product:DetailType
// }

// let pageData:PageType = {
// 	'about':{title:'xxx',desc:'aljlasdf'},
// 	'product':{title:'eeee',desc:'aaaaaaaa'},
// }

// 方法2:
interface DetailType { //约束键值类型
	title:string
	desc:string
}
type PageKey = 'about'|'product' //约束键名
let pageData:Record<PageKey,DetailType> = {
	'about':{title:'xxx',desc:'aljlasdf'},
	'product':{title:'eeee',desc:'aaaaaaaa'},
}

// 工具6：Exclude<被处理的联合类型,被排除的字段>
// 注意被操作的目标类型，必须是联合类型

type UserParam = 'name'|'age'|'score'

let key:Exclude<UserParam,'name'|'age'> = 'score'
let key1:UserParam = 'name'


// Exclude应用场景案例：联合类型 性别约束
type Gender = 'Male'|'Female'|'Other'
interface UserTypeEn {
	name?:string,
	age?:number,
	gender:Gender
}

interface UserTypeCn {
	name?:string,
	age?:number,
	gender:Exclude<Gender,'Other'>
}

//国外用户
let u1:UserTypeEn = {
	gender:'Other'
}
//国内用户
let u2:UserTypeCn = {
	gender:'Male'
}


// 工具7：Omit<被操作的接口,剔除的字段> 
// Pick的反向操作
interface IPerson7{
	id:string
	phone:number
	carId:string
}
//登记完整用户信息
let p7:IPerson7 = {
	id:'xxxx',
	phone:13677778888,
	carId:'川A66666'
}
//提供车牌号、身份证，登记免费洗车
let info7:Omit<IPerson7,'phone'> = {
	id:'xxxx',
	carId:'川A66666'
}

// 工具8：ReturnType
// 在使用三方库的时候，可以调用返回某个数据对应的类型

// 案例1：负责做加法运算的函数
let sum8 = (a:number,b:number):number=>{
	return a+b
}
console.log(sum8(3,5));

// 获取函数返回值的类型
let multi:ReturnType<typeof sum8> = 1111


//案例2：负责返回一些复杂数据包
function returnObj(){
	// 其他逻辑操作
	return {
		objectId:'19797df',
		name:'xxx',
		skills:['xxx','xxx',123]
	}
}

let o1:ReturnType<typeof returnObj> = {
	objectId:'123',
	name:'三丰',
	skills:['xxxx',11]
}

// 知识点9： type 与 interface 的异同
//interface可以重复定义，自动合并
interface Animal9 {
	name:string
}
interface Animal9 {
	color:string
}
let cat9:Animal9 = {
	name:'猫',
	color:'大桔'
}

// type 更严谨
type Animal8 = {
	name:string
}
// type Animal8 = {   //重复定义会报错
// 	color:string
// }
let cat8:Animal8 = {
	name:'猫'
}

//使用建议
// 对象约束使用interface
// 普通类型、联合类型，建议使用type
type Gender8 = 'Male'|'Female'|'Other'


// 知识点10：类型断言
interface GoodsType10{
	name:string
	price:number
	desc:string
}
//在商品数据未加载成功的时候，如果给商品设置默认值
let g:GoodsType10 = {
	name:'',
	price:0,
	desc:''
}

//使用断言 look xxx as  xxxx
let g1:GoodsType10 = {} as GoodsType10
g1.name = '商品名称'
